package com.digua.base.util

import android.view.MotionEvent
import android.view.View
import android.widget.TextView
import com.digua.base.R
import com.digua.base.util.SPUtils.remove
import com.digua.base.util.StrUtil.isBlank
import com.digua.base.util.StrUtil.isNotBlank

object ViewUtil {
    private val tag = "ViewUtil"

    /**
     * 是否非重复点击View
     *
     * @param v
     * @param reTime 重复时间
     * @return true:正常点击 false:重复点击
     */
    fun isNotReClick(v: View?, reTime: Long = 1000L) = !isReClick(v, reTime)

    /**
     * 是否重复点击View
     *
     * @param v
     * @param reTime    重复时间
     * @param igViewIds 要忽略的viewId
     * @return true:重复点击 false:非重复点击
     */
    fun isReClick(v: View?, reTime: Long = 1000L, vararg igViewIds: Int?): Boolean {
        if (v == null) return false
        if (igViewIds.contains(v.id)) return false
        val time = SPUtils.getLong(tag + v.id, 0L)
        var num = SPUtils.getInt(tag + "num" + v.id, 0)
        val cut = System.currentTimeMillis()
        if (time <= 0 || cut - time > reTime) { //不算重复操作
            SPUtils.put(tag + v.id, cut)
            remove(tag + "num" + v.id)
            return false
        }
        SPUtils.put(tag + "num" + v.id, ++num)
        if (num > 2) Toasts.showShort(R.string.frequent_operations)
        return true
    }

    /**
     * 是否重复点击View 针对部分封装后点击事件中没有View的(少于500毫秒算重复点击)
     *
     * @param obj
     * @return false:重复点击 true:非重复点击
     */
    fun isNoReClickByObj(obj: Any?, clz: Class<*>? = null) = !isReClickByObj(obj, clz)

    /**
     * 是否重复点击View 针对部分封装后点击事件中没有View的
     *
     * @param obj
     * @param reTime 重复时间
     * @return true:重复点击 false:非重复点击
     */
    fun isReClickByObj(obj: Any?, clz: Class<*>? = null, reTime: Long = 1000L): Boolean {
        if (obj == null) return false
        val key = "_obj_${clz?.simpleName + obj}"
        val time = SPUtils.getLong(tag + key, 0L)
        var num = SPUtils.getInt(tag + "num" + key, 0)
        val cut = System.currentTimeMillis()
        SPUtils.put(tag + key, cut)
        if (time <= 0 || cut - time > reTime) { //不算重复操作
            remove(tag + "num" + key)
            return false
        }
        SPUtils.put(tag + "num" + key, ++num)
        if (num > 2) Toasts.showShort(R.string.frequent_operations)
        return true
    }

    /**
     * 是否重复点击View 针对部分封装后点击事件中没有View的(少于500毫秒算重复点击)
     *
     * @param obj
     * @return false:重复点击 true:非重复点击
     */
    fun isNoReActionByObj(obj: Any?, clz: Class<*>? = null) = !isReActionByObj(obj, clz)

    /**
     * 是否重复点击View 针对部分封装后点击事件中没有View的
     *
     * @param obj
     * @param reTime 重复时间
     * @return true:重复点击 false:非重复点击
     */
    fun isReActionByObj(obj: Any?, clz: Class<*>? = null, reTime: Long = 1000L): Boolean {
        if (obj == null) return false
        val key = "_obj_${clz?.simpleName + obj}"
        val time = SPUtils.getLong(tag + key, 0L)
        val cut = System.currentTimeMillis()
        SPUtils.put(tag + key, cut)
        //不算重复操作
        return !(time <= 0 || cut - time > reTime)
    }

    /**
     * 是否重复点击View 针对部分封装后点击事件中没有View的
     *
     * @param obj
     * @param reTime 重复时间
     * @return true:重复点击 false:非重复点击
     */
    fun isReActionByObjSingle(obj: Any?, reTime: Long): Boolean {
        if (obj == null) return false
        val key = "_obj_$obj"
        val time = SPUtils.getLong(tag + key, 0L)
        val cut = System.currentTimeMillis()
        if (time <= 0 || cut - time > reTime) { //不算重复操作
            SPUtils.put(tag + key, cut)
            return false
        }
        return true
    }

    /**
     * 获取控件值转Integer
     *
     * @param view
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getValInteger(view: V, defVal: Int? = null) = NumUtil.parseInteger(getVal<V>(view), defVal)

    /**
     * 获取控件值 为空值是Toast提示
     *
     * @param view
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getValIntegerAndNullToast(view: V, errTitle: String? = null): Int? {
        val res = getValInteger(view)
        if (res == null && isNotBlank(errTitle)) {
            Toasts.showLong(errTitle!!)
        }
        return res
    }

    /**
     * 获取控件值 为空值是Toast提示
     *
     * @param view
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getValIntegerAndGtToast(view: V, errTitle: String? = null, min: Int = 0): Int? {
        val res = getValInteger(view)
        if ((res == null || res < min) && isNotBlank(errTitle)) {
            Toasts.showLong(errTitle!!)
        }
        return res
    }

    /**
     * 获取控件值 为空值是Toast提示
     *
     * @param view
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getValIntegerAndGeToast(view: V, errTitle: String? = null, min: Int = 0): Int? {
        val res = getValInteger(view)
        if ((res == null || res <= min) && isNotBlank(errTitle)) {
            Toasts.showLong(errTitle!!)
        }
        return res
    }

    /**
     * 获取控件值转Integer
     *
     * @param view
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getValFloat(view: V, defVal: Float? = null) = NumUtil.parseFloat(getVal<V>(view), defVal)

    /**
     * 获取控件值 为空值是Toast提示
     *
     * @param view
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getValFloatAndNullToast(view: V, errTitle: String? = null): Float? {
        val res = getValFloat(view)
        if (res == null && isNotBlank(errTitle)) {
            Toasts.showLong(errTitle!!)
        }
        return res
    }

    /**
     * 获取控件值 为空值是Toast提示
     *
     * @param view
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getValFloatAndGtToast(view: V, errTitle: String? = null, min: Float = 0F): Float? {
        val res = getValFloat(view)
        if ((res == null || res < min) && isNotBlank(errTitle)) {
            Toasts.showLong(errTitle!!)
        }
        return res
    }

    /**
     * 获取控件值 为空值是Toast提示
     *
     * @param view
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getValFloatAndGeToast(view: V, errTitle: String? = null, min: Float = 0F): Float? {
        val res = getValFloat(view)
        if ((res == null || res <= min) && isNotBlank(errTitle)) {
            Toasts.showLong(errTitle!!)
        }
        return res
    }

    /**
     * 获取控件值转Double
     *
     * @param view
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getValDouble(view: V, defVal: Double? = null) = NumUtil.parseDouble(getVal<V>(view), defVal)

    /**
     * 获取控件值 为空值是Toast提示
     *
     * @param view
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getValDoubleAndNullToast(view: V, errTitle: String? = null): Double? {
        val res = getValDouble(view)
        if (res == null && isNotBlank(errTitle)) {
            Toasts.showLong(errTitle!!)
        }
        return res
    }

    /**
     * 获取控件值 为空值是Toast提示
     *
     * @param view
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getValDoubleAndGtToast(view: V, errTitle: String? = null, min: Double = 0.0): Double? {
        val res = getValDouble(view)
        if ((res == null || res < min) && isNotBlank(errTitle)) {
            Toasts.showLong(errTitle!!)
        }
        return res
    }

    /**
     * 获取控件值 为空值是Toast提示
     *
     * @param view
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getValDoubleAndGeToast(view: V, errTitle: String? = null, min: Double = 0.0): Double? {
        val res = getValDouble(view)
        if ((res == null || res <= min) && isNotBlank(errTitle)) {
            Toasts.showLong(errTitle!!)
        }
        return res
    }

    /**
     * 获取控件值
     *
     * @param view
     * @param defVal 默认值
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getVal(view: V?, defVal: String? = null) = view?.text?.toString() ?: defVal

    /**
     * 获取控件值 为空值是Toast提示
     *
     * @param view
     * @param <V>
     * @return
    </V> */
    fun <V : TextView?> getValAndNullToast(view: V?, errTitle: String? = null): String? {
        val value = getVal<V?>(view)
        if (isBlank(value) && isNotBlank(errTitle)) {
            Toasts.showLong(errTitle!!)
        }
        return value
    }

    /**
     * 获取控件值 为空值是Toast提示
     *
     * @param view
     * @return
     */
    fun setVisible(view: View?, isVisible: Boolean) = view?.apply { visibility = if (isVisible) View.VISIBLE else View.GONE }

    /**
     * 批量设置组件点击事件
     *
     * @param views
     * @param listener
     */
    fun setOnClickListener(vararg views: View, listener: (view: View) -> Unit) {
        if (views.isNotEmpty()) {
            for (view in views) {
                view.setOnClickListener(listener)
            }
        }
    }

    /**
     * 批量设置组件点击事件
     *
     * @param views
     * @param listener
     */
    fun setOnLongClickListener(vararg views: View, listener: (view: View) -> Boolean) {
        if (views.isNotEmpty()) {
            for (view in views) {
                view.setOnLongClickListener(listener)
            }
        }
    }

    /**
     * 批量设置组件触摸事件
     *
     * @param views
     * @param listener
     */
    fun setOnTouchListener(vararg views: View, listener: (view: View, evn: MotionEvent) -> Boolean) {
        if (views.isNotEmpty()) {
            for (view in views) {
                view.setOnTouchListener(listener)
            }
        }
    }

    /**
     * 批量设置组件点击事件
     *
     * @param view
     * @param listener
     */
    fun onClick(view: View?, listener: (view: View) -> Unit) {
        if (view == null) return
        view.setOnClickListener(listener)
    }

    /**
     * 设置组件防重点点击事件
     *
     * @param view
     * @param listener
     */
    fun onClickNoReClick(view: View?, listener: (view: View) -> Unit) {
        if (view == null) return
        view.setOnClickListener(View.OnClickListener {
            if (!isReClick(it)) listener(it)
        })
    }

    /**
     * 批量设置组件防重点点击事件
     *
     * @param views
     * @param listener
     */
    fun onClickNoReClick(vararg views: View, listener: (view: View) -> Unit) {
        if (views.isEmpty()) return
        for (view in views) {
            view.setOnClickListener {
                if (!isReClick(it)) listener(it)
            }
        }
    }

    /**
     * 批量设置组件防重点点击事件
     *
     * @param views
     * @param num 点击次数
     * @param listener
     */
    fun onClickNumber(num: Int, vararg views: View, listener: (view: View) -> Unit) {
        if (views.isEmpty()) return
        for (view in views) {
            view.setOnClickListener {
                if (reClickNum(it, 500L, num)) listener(it)
            }
        }
    }

    /**
     * 是否重复点击View
     *
     * @param v
     * @param reTime    重复时间
     * @param igViewIds 要忽略的viewId
     * @return true:重复点击 false:非重复点击
     */
    private fun reClickNum(v: View, reTime: Long = 1000L, num: Int, vararg igViewIds: Int?): Boolean {
        if (igViewIds.contains(v.id)) return false
        val time = SPUtils.getLong(tag + v.id, 0L)
        var temp = SPUtils.getInt(tag + "num" + v.id, 0)
        val cut = System.currentTimeMillis()
        SPUtils.put(tag + v.id, cut)
        if (time <= 0 || cut - time > reTime) { //不算重复操作
            remove(tag + "num" + v.id)
            SPUtils.put(tag + "num" + v.id, 0)
            return false
        }
        return if (temp >= num) {
            SPUtils.put(tag + "num" + v.id, 0)
            true
        } else {
            SPUtils.put(tag + "num" + v.id, ++temp)
            false
        }
    }

    /**
     * 记录次数
     *
     * @param key  key值
     * @param num  记录操作的次数
     * @param time 有效间隔时间
     */
    fun recordNum(key: String, num: Int, time: Long): Boolean {
        if (isBlank(key) || num <= 0 || time <= 0) return false
        val oldTime = SPUtils.getLong(tag + key, 0L)
        SPUtils.put(tag + key, System.currentTimeMillis())
        if (System.currentTimeMillis() - oldTime > time) {
            SPUtils.put(tag + "num", 1)
            return false
        }
        val oldNum = SPUtils.getInt(tag + "num", 0)
        SPUtils.put(tag + "num", if (oldNum >= num) 0 else (oldNum + 1))
        return oldNum >= num
    }

}
